home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 6
/
FM Towns Free Software Collection 6.iso
/
t_os
/
chtiff
/
source
/
chtiff4.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-08
|
4KB
|
210 lines
/* LZW圧縮法による、TIFF画像データ処理部 */
#include<stdio.h>
#include<stdlib.h>
#define COMPRESS_SECTION 1
#include"define.h"
#include"function.h"
#define CLEAR_CODE 256
#define EOF_CODE 257
#define MAXTABLE 4096
unsigned int header[ MAXTABLE ];
unsigned int table_next[ MAXTABLE ];
unsigned short table_ch[ MAXTABLE ];
unsigned int table_high[ MAXTABLE ];
unsigned int table_low[ MAXTABLE ];
unsigned int cbl;
unsigned int table_ix;
unsigned int add_with;
unsigned char *add;
unsigned long uncomp_bytes;
void init_table(void)
{
int i;
putchar('>');
for(i=0; i<256; i++){
table_ch[i] = i;
table_next[i] = table_high[i] = table_low[i] = MAXTABLE+1;
}
for(i=0; i<MAXTABLE; i++){
header[i] = MAXTABLE+1;
}
}
int tsearch(int s, int c)
{
int stp; /* search table pointer */
if( s == MAXTABLE+1 ) return( c );
stp = header[s]; /* 末尾のNEXTがsであるやつの集まり */
LOOP:
if( stp == MAXTABLE+1 ){
return(MAXTABLE+1);
}
if( table_ch[ stp ] == c ){
return( stp );
}
add_with = stp;
if( table_ch[ stp ] < c ){
stp = table_high[stp];
goto LOOP;
}
stp = table_low[stp];
goto LOOP;
}
void add_entry(int s, int c)
{
/*
s: コード番号を差す。コードのにcを付け足したのがs:cであり、
そいつのコード番号はtable_ixである。
*/
table_next[ table_ix ] = s;
table_ch[ table_ix ] = c;
/* 以後検索のための設定 */
table_high[ table_ix ] = table_low[ table_ix ] = MAXTABLE+1;
if( header[s] == MAXTABLE+1 ){
header[s] = table_ix;
table_ix++;
return;
}
if( c > table_ch[ add_with ] ){
table_high[ add_with ] = table_ix;
table_ix++;
return;
}
table_low[add_with] = table_ix;
table_ix++;
return;
}
void put_code(short ch)
{
unsigned static long a = 0; /* ビット操作作業用 */
unsigned static int PackedBits = 0; /* aに入っている有効ビット数 */
unsigned static char start_add[4100], *pc;
unsigned static long stack_bytes = 0, put_bytes = 0;
static short mask_table[4] = {0x1ff, 0x3ff, 0x7ff, 0xfff};
static int INIT = 0;
unsigned long chl; /* ch of long bytes */
if(INIT==0){
pc = start_add;
put_bytes = stack_bytes = PackedBits = a = 0;
INIT=1;
}
chl = ch & mask_table[cbl-9]; /* 念のため不要ビットはマスク */
a <<= cbl;
a |= chl;
PackedBits += cbl-8; /* ここでは、8ビット以上が何ビットかを表わす */
/* 必ず1バイトは出力するはず(嗚呼、コンパイラー依存)*/
*pc = (a >> PackedBits);
pc++;
stack_bytes++;
put_bytes++;
if(PackedBits >= 8){
PackedBits -= 8;
*pc = (a >> PackedBits) & 0xff;
pc++;
stack_bytes++;
put_bytes++;
}
if( stack_bytes >= 4095 ){
fwrite(start_add, stack_bytes, 1, to.fp);
pc = start_add;
stack_bytes = 0;
}
if(ch != EOF_CODE) return;
put_bytes += 2;
printf(" write %lu bytes\n",put_bytes );
*(to.Strips_ByteCount + to.Strips) = put_bytes;
*pc = (a << (8-PackedBits)) & 0xff;
stack_bytes += 2;
fwrite(start_add, stack_bytes , 1, to.fp);
INIT = 0;
return;
}
void compress(unsigned char *a, unsigned long b)
{
unsigned short s,p;
unsigned short ch;
add = a;
uncomp_bytes = b;
printf("Compress %lu bytes ", uncomp_bytes);
init_table();
cbl=9;
table_ix = EOF_CODE + 1;
put_code( CLEAR_CODE );
s = MAXTABLE+1;
while( uncomp_bytes ){
ch = *add;
add++;
uncomp_bytes--;
/* S:Cがテーブル内に存在するか? */
if( (p = tsearch(s, ch)) != MAXTABLE+1 ){
s = p; /* S <- S:C */
}
else{
/* Sのインデックスを出力 */
put_code(s);
if( table_ix < MAXTABLE-2 ){
/* S:Cをテーブルに登録 */
add_entry(s, ch);
if( table_ix == (1<<cbl) ) cbl++;
}
else{
/* クリアコード出力 */
put_code( CLEAR_CODE );
init_table();
cbl = 9;
table_ix = EOF_CODE+1;
}
/* S <- C */
s = ch;
}
}
/* Sのインデックスを出力 */
put_code( s );
put_code( EOF_CODE );
}